# 迭代优化接入的对比情况

import itertools as it

from .dinkelbach_user_association import user_association
from .performance_calculations import compute_CE, compute_E_vector, compute_comsume_pv_city_e
from ..model.models import Onetimeresult, Sleepaction

from .performance_calculations import compute_B
from .system_initialization import *
# 迭代优化接入的对比情况

import itertools as it


#  用户关联的主函数
#  用户关联的主函数
def userassociation_energysharing_once(bs_num, ue_num, bs_pos, ue_pos, p_pv, rb_req, l_bs_ue, h_bs_ue):
    '''
    用户关联的主函数
    :param bs_num:基站数
    :param ue_num: 用户数
    :param bs_pos: 基站位置
    :param ue_pos: 用户位置
    :param p_pv: 光伏能量
    :param rb_req: 用户需求资源块数
    :param l_bs_ue: 基站用户距离
    :param h_bs_ue: 基站用户信道状态
    :return:最优结果Onetimeresult
    '''

    bs_status_all = list(it.product(range(2), repeat=bs_num - 1))
    bs_status_list = []
    for i in range(len(bs_status_all)):
        bs_status = list(bs_status_all[i])
        bs_status.insert(0, int(1))
        bs_status = np.array(bs_status)[np.newaxis, :]
        bs_status_list.append(bs_status)

    # 所有结果
    result_all = []
    result_optimal = Onetimeresult(ce=0)
    result_without_association_optimal = Onetimeresult(ce=0)
    result_unsleep = Onetimeresult(ce=0)
    action_all = []
    action_optimal = []
    final_i = 0
    for i in range(len(bs_status_list)):
        bs_status = bs_status_list[i]
        # res_x_bs_ue = np.zeros([ue_num, bs_num])

        # 就近接入时的连接矩阵
        res_x_bs_ue_raw = nearby_access(bs_pos, ue_pos, bs_status, rb_req)  # 就近接入

        converged = False
        loop = 1
        L = 100
        flag = False
        # 特殊情况 i==0 只有宏基站，直接就近接入
        # print('*****************************************************************')
        print('第' + str(i) + '种基站休眠情况开始计算!')

        # 不使用 user_association 函数的情况
        res_x_bs_ue_without_association = res_x_bs_ue_raw.copy()
        p_bs_without_association, _ = bs_energy_consumption_calculation(bs_status, res_x_bs_ue_without_association,
                                                                        rb_req)

        # action_without_association = Sleepaction(bs_status=bs_status, x_bs_ue=res_x_bs_ue_without_association)
        # action_all_without_association.append(action_without_association)

        # 计算结果变量
        r_ue_without_association, _, delta_connected_without_association = rate_sum_calculation(
            res_x_bs_ue_without_association, h_bs_ue, l_bs_ue, rb_req)
        b_ue_without_association = compute_B(res_x_bs_ue_without_association, h_bs_ue, l_bs_ue, rb_req)
        p_bs_without_association, _ = bs_energy_consumption_calculation(bs_status, res_x_bs_ue_without_association,
                                                                        rb_req)
        # 计算碳排放量
        e_co2_without_association = compute_E_vector(res_x_bs_ue_without_association, p_pv, bs_status, rb_req)
        ce_without_association = compute_CE(res_x_bs_ue_without_association, p_pv, bs_status, h_bs_ue, l_bs_ue, rb_req)
        consume_pv_without_association, city_e_without_association = compute_comsume_pv_city_e(res_x_bs_ue_without_association, p_pv, bs_status, h_bs_ue)
        pv_rate_without_association = consume_pv_without_association / p_pv.sum() * 100
        print('第' + str(i) + '种情况（不使用 user_association）成功收敛!收敛轮次为：', loop)
        print('第' + str(i) + '种情况（不使用 user_association）对应的基站状态时：', bs_status)
        print('look!第' + str(i) + '种情况（不使用 user_association）的碳效率为', f'{ce_without_association:.2e}')

        result_without_association = Onetimeresult(bs_status=bs_status, ce=ce_without_association,
                                                   B=b_ue_without_association, E_carbon=e_co2_without_association,
                                                   delta_connected=delta_connected_without_association,
                                                   p_bs=p_bs_without_association,
                                                   system_status=True, x_bs_ue=res_x_bs_ue_without_association,
                                                   r_ue=r_ue_without_association, consume_pv = consume_pv_without_association,
                                                   city_e=city_e_without_association, pv_rate=pv_rate_without_association)

        if result_without_association.ce > result_without_association_optimal.ce:
            result_without_association_optimal = result_without_association

        # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        # 优化用户关联，是优化的核心之一
        # 优化用户关联情况下

        # 基站用户关联变量
        res_x_bs_ue = user_association(res_x_bs_ue_raw, bs_status, p_pv, rb_req, l_bs_ue, h_bs_ue)

        # 基站能耗
        p_bs, _ = bs_energy_consumption_calculation(bs_status, res_x_bs_ue, rb_req)

        # 暂时可以不需要
        # action = Sleepaction(bs_status=bs_status, x_bs_ue=res_x_bs_ue)
        # action_all.append(action)

        # 计算结果变量
        # 计算速率
        # r_ue用户速率矩阵    delta_connected用户服务质量满足情况
        r_ue, _, delta_connected = rate_sum_calculation(res_x_bs_ue, h_bs_ue, l_bs_ue, rb_req)

        # b_ue 1h所有用户的数据量 R*3600
        b_ue = compute_B(res_x_bs_ue, h_bs_ue, l_bs_ue, rb_req)

        # p_bs 基站能耗     bs_rb_access 基站已用资源块
        p_bs, _ = bs_energy_consumption_calculation(bs_status, res_x_bs_ue, rb_req)

        # 计算碳排放量
        e_co2 = compute_E_vector(res_x_bs_ue, p_pv, bs_status, rb_req)

        # 计算碳效CE， 消耗光伏能量，市电量
        ce = compute_CE(res_x_bs_ue, p_pv, bs_status, h_bs_ue, l_bs_ue, rb_req)
        consume_pv, city_e = compute_comsume_pv_city_e(res_x_bs_ue, p_pv, bs_status, h_bs_ue)
        pv_rate = consume_pv / p_pv.sum() * 100
        print('第' + str(i) + '种情况成功收敛!收敛轮次为：', loop)
        print('第' + str(i) + '种情况对应的基站状态时：', bs_status)
        print('look!第' + str(i) + '种情况的碳效率为', f'{ce:.2e}')

        # 需要对于这里进行修改，增添需要的元素

        result = Onetimeresult(bs_status=bs_status, ce=ce, B=b_ue, E_carbon=e_co2,
                               delta_connected=delta_connected, p_bs=p_bs,
                               system_status=True, x_bs_ue=res_x_bs_ue, r_ue=r_ue,
                               consume_pv=consume_pv, city_e=city_e, pv_rate=pv_rate)

        # 求取最优碳效率,最后的result_optimal为结果
        if result.ce > result_optimal.ce:
            result_optimal = result
            # action_optimal = action
            final_i = i

        # 需要基站全部不休眠的结果result_unsleep
        if i == len(bs_status_list) - 1:
            result_unsleep = Onetimeresult(bs_status=bs_status, ce=ce, B=b_ue, E_carbon=e_co2,
                                           delta_connected=delta_connected, p_bs=p_bs,
                                           system_status=True, x_bs_ue=res_x_bs_ue, r_ue=r_ue,
                                           consume_pv=consume_pv, city_e=city_e, pv_rate=pv_rate)
        # result_all.append(result)

    if result_optimal.ce != 0:
        print("===============================================================================\n")
        print('在用户关联且基站休眠的最优结果下，当前时刻有最优解！')
        print(f"其对应的轮次是{final_i}")
        print(f"其对应的基站状态是{result_optimal.bs_status}")
        print(f"其对应的ce是{result_optimal.ce}")
        print(f"其对应的碳排放量是{result_optimal.E_carbon}")

    # 暂时不用管result_unsleep的警告，result_unsleep必然有结果
    # 依次返回一下三个结果：1.用户关联且基站休眠的最优结果    2.用户关联但是基站不休眠优化结果  3.就近接入（用户不关联）基站休眠优化结果
    result_optimal.set_info("用户关联且基站休眠的最优结果")
    result_unsleep.set_info("用户关联但是基站不休眠优化结果")
    result_without_association_optimal.set_info("就近接入（用户不关联）基站休眠优化结果")
    return result_optimal, result_unsleep, result_without_association_optimal


def print_Onetimeresult(result):
    # if isinstance(result, Onetimeresult):
    #     raise TypeError("输入必须Onetimeresult类型")
    print("===============================================")
    print(f"当前打印的是{result.additional_info}:")
    print(f"其对应的基站状态是{result.bs_status}")
    print(f"其对应的ce是{result.ce}")
    print(f"其对应的最终用户关联策略是{result.x_bs_ue}")
    print(f"其对应的用户速率是{result.r_ue}")
    print(f"其对应的基站功耗是{result.p_bs}")
    print(f"其对应的碳排放量是{result.E_carbon}")
    print(f"其对应的用户的数据量是{result.B}")

#
# if __name__ == '__main__':
#     ue_num = 30
#     bs_num = 2
#     # ue_num = const.UE_NUM_SEQUENCE[0]
#     const.modify_const("BS_NUM", bs_num)
#     const.modify_const("RB_MAX", get_RB_MAX(bs_num))
#     const.modify_const("RB_W", get_RB_W(bs_num))
#     const.modify_const("P_WORK", get_P_WORK(bs_num))
#     const.modify_const("P_SLEEP", get_P_SLEEP(bs_num))
#     const.modify_const("ONE_BS", get_ONE_BS(bs_num))
#     const.modify_const("ZERO_BS", get_ZERO_BS(bs_num))
#
#     print("接下来打印修改之后的结果")
#     print(const.BS_NUM)
#     print(const.RB_MAX)
#     print(const.RB_W)
#     print(const.P_WORK)
#     print(const.P_SLEEP)
#     print(const.ONE_BS)
#     print(const.ZERO_BS)
#     bs_pos = uniform2d(bs_num - 1, const.L)
#     bs_pos = macro_bs_init(bs_pos, const.L)
#     ue_pos = uniform2d(ue_num, const.L)
#     print(bs_pos)
#     print(ue_pos)
#
#     # 初始化光伏能量
#     p_pv = np.random.poisson(const.PV_A, [1, bs_num])  # shape=[24, bs_num]
#     s_pv = [const.S_PV_MICRO for i in range(bs_num - 1)]
#     s_pv.insert(0, const.S_PV_MACRO)
#     p_pv = p_pv * s_pv * const.GAMMA_PV
#
#     # 初始化用户要求和信道状态
#     ue_snr_theta = np.random.randint(const.SINR_MIN, const.SINR_MAX, size=[ue_num, 1])
#     h_bs_ue = channel_status(bs_num, ue_num)
#
#     bs_status = np.array([[1, 0, 0, 0]])
#     ce_temp = 1000
#     l_bs_ue = distance_calculation(bs_pos, ue_pos)  # 测算距离
#     _, rb_req = rb_demand(ue_snr_theta, l_bs_ue, h_bs_ue)
#     # result_userassociation_energysharing = userassociation_energysharing_once(bs_num, ue_num, bs_pos, ue_pos, p_pv,
#     #                                                                           rb_req, l_bs_ue, h_bs_ue)
#     result_optimal, result_unsleep, result_without_association_optimal \
#         = userassociation_energysharing_once(bs_num, ue_num, bs_pos, ue_pos, p_pv, rb_req, l_bs_ue, h_bs_ue)
#
#     print("现在进入到最终结果的打印:")
#     print_Onetimeresult(result_optimal)
#     # print_Onetimeresult(result_unsleep)
#     # print_Onetimeresult(result_without_association_optimal)
#
#     # print("测试直接优化打印")
#     # print(result_optimal)
#
#     bs_ue = result_optimal.x_bs_ue
#     # 更新用户的归属的基站，对于每一个最后的优化结果进行遍历
#     # 需要注意，在这里基站的序号从0开始
#     belong_list = [ 0 for _ in range(bs_num)]
#     for i in range(ue_num):
#         # 获取所属的基站序号，查找1
#         idx = bs_ue[i].tolist().index(1)
#         belong_list[idx] += 1
#         print(f"用户{i+1}所属的基站是{idx+1}")
#         # 写入当前用户的数据库，指明所属基站以及属于基站的第几个用户
#         update_scene_user_element(Session, "bs_identifier", idx+1, time_id=0, time_userrank=i+1)
#         update_scene_user_element(Session, "user_id_scene", belong_list[idx], time_id=0, time_userrank=i+1)
#
#     print("最终的归属结果是")
#     print(belong_list)
#     print(sum(belong_list))
# 成功完成测试
# 最终的归属结果是
# [13, 17]
# 30
